#include "cmd.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

void CCLIUsage(CcliCmd * cmd){
    printf("%s\n", cmd->usage);
    CcliCmd *ptr = cmd->subCmd;
    while(ptr){
        printf("%s/t%s", ptr->name, ptr->description);
        ptr = cmd->nextCmd;
    }
}

void CCLIUsageExit(CcliCmd * cmd){
    CCLIUsage(cmd);
    exit(-1);
}

// CCLICmdInit: ./cmd subcmd. if arg not match subcmd'subcmd, then call handler
CcliCmd *CCLISubCmdInit(char *name, char *usage, CCLICmdHandler handler){
    if(!name){
        printf("sub cmd's name should not be NULL\n");
        exit(-1);
    }
    if(!usage){
        printf("sub cmd's usage should not be NULL\n");
        exit(-1);
    }
    CcliCmd *cmd = malloc(sizeof(*cmd));
    memset(cmd, 0, sizeof(*cmd));
    cmd->name = strdup(name);
    cmd->usage = strdup(usage);
    cmd->handler = handler;
    return cmd;
}

// CCLICmdInit: the root cmd's name is "", it can't match any cmd name
CcliCmd *CCLIRootCmdInit(char *usage, CCLICmdHandler *handler){
    return CCLISubCmdInit("", usage, handler);
}

// CCLICmdAddSubCmd: Add subcmd to cmd, add to cmd->subCmd->lastCmd->nextCmd
int CCLICmdAddSubCmd(CcliCmd *cmd, CcliCmd *subCmd){
    if(!cmd || !subCmd){
        printf("cmd should not be NULL\n");
        exit(-1);
    }

    if(cmd->subCmd == NULL){
        cmd->subCmd = subCmd;
        cmd->lastCmd = subCmd;
    }else{
        cmd->lastCmd->nextCmd = subCmd;
        cmd->lastCmd = subCmd;
    }
}

// Exec: parse input argc and args, argv[0] is the parent cmd
int CCLICmdExec(CcliCmd *cmd, int argc, char **argv){
    if(!cmd){
        printf("cmd should not be NULL\n");
        exit(-1);
    }

    if(argc > 1){
        if(strcmp(argv[1], "-h") == 0)
            CCLIUsageExit(cmd);
        if(strcmp(argv[1], "--help") == 0)
            CCLIUsageExit(cmd);

        CcliCmd *ptr = cmd->subCmd;
        while(ptr){
            if(strcmp(argv[1], ptr->name) == 0){
                return CCLICmdExec(ptr, argc - 1, argv + 1);
            }
            ptr = cmd->nextCmd;
        }
    }
    return cmd->handler(argc - 1, argv + 1);
}